package conson.tech.manage.coupons.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import conson.tech.core.exception.BaseException;
import conson.tech.core.response.Response;
import conson.tech.manage.common.constant.BusinessMessage;
import conson.tech.manage.common.util.ExcelUtils;
import conson.tech.manage.common.util.TimeUtils;
import conson.tech.manage.coupons.constant.CouponsConstants;
import conson.tech.manage.coupons.entity.dto.*;
import conson.tech.manage.coupons.entity.pojo.*;
import conson.tech.manage.coupons.entity.vo.*;
import conson.tech.manage.coupons.feign.UserFeignService;
import conson.tech.manage.coupons.feign.dto.UserQueryDTO;
import conson.tech.manage.coupons.mapper.*;
import conson.tech.manage.coupons.service.CouponActivityService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * InterfaceName: CouponActivityServiceImpl
 * Description: 领券活动业务接口实现类
 * Author: XYF
 * Date: 2020/7/21 11:26
 * Version: 1.0
 */
@Slf4j
@Service
public class CouponActivityServiceImpl implements CouponActivityService {

    @Autowired
    private ActivityMapper activityMapper;

    @Autowired
    private ActivityCouponsMapper activityCouponsMapper;

    @Autowired
    private CouponsBatchMapper couponsBatchMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private OperationLogMapper operationLogMapper;

    @Autowired
    private ActivityUserMapper activityUserMapper;

    @Autowired
    private CouponsUsersMapper couponsUsersMapper;

    @Autowired
    private CouponsUsersLogMapper couponsUsersLogMapper;

    @Autowired
    private SettlementReportMapper settlementReportMapper;

    @Autowired
    private CouponsCostProviderMapper couponsCostProviderMapper;

    @Autowired
    private CouponsUsingRangeMapper couponsUsingRangeMapper;

    @Autowired
    private MerchantInformationMapper merchantInformationMapper;

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private UserFeignService userFeignService;


    /**
     * 作废领券活动
     *
     * @param currentUserId
     * @param id
     * @return conson.tech.core.response.Response
     */
    @Override
    @Transactional
    public Response giveUpCouponActivity(Long currentUserId, String currentUsername, Long id) {

        log.info("作废领券活动");
        Activity activity = this.activityMapper.selectById(id);
        if (activity == null) {
            throw new BaseException(BusinessMessage.ACTIVITY_NOT_EXISTS_ERROR);
        }
        if (activity.getStatus() != 1) {
            throw new BaseException(BusinessMessage.ACTIVITY_STATUS_ERROR);
        }
        if (activity.getCollectType() == 1) {
            throw new BaseException(BusinessMessage.ACTIVITY_TYPE_ERROR);
        }
        // 初始状态下才能作废
        activity.setStatus(4);
        activity.setUpdateTime(LocalDateTime.now());
        activity.setUpdateBy(currentUserId);
        this.activityMapper.updateById(activity);

        //作废领券活动，录入活动操作日志表
        OperationLogDto opera = new OperationLogDto();
        opera.setCreateBy(currentUsername);
        opera.setDomainId(activity.getId());
        opera.setOperateDesc("作废领券活动");
        this.editLog(opera);

        log.info("作废领券活动完成");
        return Response.success(activity.getId());
    }

    /**
     * 强制结束领券活动
     *
     * @param currentUserId
     * @param id
     * @return conson.tech.core.response.Response
     */
    @Override
    @Transactional
    public Response overCouponActivity(Long currentUserId, String currentUsername, Long id) {

        log.info("强制结束领券活动");
        Activity activity = this.activityMapper.selectById(id);
        if (activity == null) {
            throw new BaseException(BusinessMessage.ACTIVITY_NOT_EXISTS_ERROR);
        }
        if (activity.getStatus() != 2) {
            throw new BaseException(BusinessMessage.ACTIVITY_STATUSN_NOT_ON_ERROR);
        }
        // 进行中状态下才能强制结束
        activity.setStatus(3);
        activity.setUpdateTime(LocalDateTime.now());
        activity.setUpdateBy(currentUserId);

        this.activityMapper.updateById(activity);

        OperationLogDto opera = new OperationLogDto();
        opera.setCreateBy(currentUsername);
        opera.setDomainId(activity.getId());
        opera.setOperateDesc("修改领券活动");
        this.editLog(opera);

        //        强制结束完将活动库存放入到优惠券绑定表中
        List<ActivityCoupons> activityCouponsList = this.activityCouponsMapper.selectList(new QueryWrapper<ActivityCoupons>().eq("activity_id", activity.getId()));
        for (ActivityCoupons activityCoupons : activityCouponsList) {

            //将参与活动的批次信息中库存存入到redis中
            String activityStock = redisTemplate.opsForValue().get(CouponsConstants.ACTIVITY_COUPON_PREFIX + activity.getId() + ":" + activityCoupons.getBatchId());
            if (activityStock != null) {
                activityCoupons.setSurplusNum(Integer.valueOf(activityStock));
            }
            activityCoupons.setUpdateBy(currentUserId);
            activityCoupons.setUpdateTime(LocalDateTime.now());
            this.activityCouponsMapper.updateById(activityCoupons);

            try {
                redisTemplate.delete(CouponsConstants.ACTIVITY_COUPON_PREFIX + activity.getId() + ":" + activityCoupons.getBatchId());
            } catch (Exception e) {
                throw new BaseException(BusinessMessage.ACTIVITY_CLEAR_ERROR);
            }

        }

        //强制结束领券活动，录入活动操作日志表
        OperationLogDto opera1 = new OperationLogDto();
        opera1.setCreateBy(currentUsername);
        opera1.setDomainId(activity.getId());
        opera1.setOperateDesc("强制结束领券活动");
        this.editLog(opera1);

        log.info("强制结束领券活动完成");
        return Response.success(activity.getId());
    }

    /**
     * 定向发放优惠券活动 导入用户列表
     *
     * @param currentUserId
     * @param file
     * @param id
     * @param response
     * @return conson.tech.core.response.Response
     */
    @Override
    @Transactional
    public Response bindingUsers(Long currentUserId, MultipartFile file, Long id, HttpServletResponse response) throws Exception {

        log.info("定向发放优惠券活动导入用户列表开始");

        List<UserVo> list = ExcelUtils.read(file, UserVo.class);

        List<String> collect = list.stream().map(UserVo::getPhoneNum).collect(Collectors.toList());
        //           TODO 远程调用用户模块 验证用户手机号，是否存在
        UserQueryDTO userQueryDTO = new UserQueryDTO();
        userQueryDTO.setMobileList(collect);
        Response response1 = this.userFeignService.queryUserIdByMobile(userQueryDTO);
        if (response1.getCode() == 200) {
//                解析得到导入用户的id
            List<UserQueryDTO> data = Convert.convert(new TypeReference<List<UserQueryDTO>>() {
            }, response1.getResult());
//            如果这里导入失败，则生成导入失败的报表
//            将未匹配到的userId的手机号区分出来
            List<String> collect1 = data.stream().map(UserQueryDTO::getMobile).collect(Collectors.toList());

            List<BindingUserWithFailVo> bindingUserWithFailVos = new ArrayList<>();
            for (int i = 0; i < collect.size(); i++) {

                BindingUserWithFailVo vo = new BindingUserWithFailVo();
                vo.setNum(i);
                vo.setPhoneNum(collect.get(i));
                if (!collect1.contains(collect.get(i))) {
                    vo.setNote("手机号码不存");
                }
                bindingUserWithFailVos.add(vo);
            }
            if (bindingUserWithFailVos.size() == collect1.size()) {
//            如果这里导入成功，则直接进行优惠券发放
//            如果这些数据都存在，则进行用户优惠券绑定
                //            验证活动是否在存在
                Activity activity = this.activityMapper.selectById(id);
                if (activity == null) {
                    throw new BaseException(BusinessMessage.ACTIVITY_NOT_EXISTS_ERROR);
                }
                //            验证活动状态
                if (activity.getStatus() == 3 || activity.getStatus() == 4) {
                    throw new BaseException(BusinessMessage.ACTIVITY_OVER_INVALID_ERROR);
                }

                ActivityCoupons activityCoupons = this.activityCouponsMapper.selectOne(new QueryWrapper<ActivityCoupons>().eq("activity_id", activity.getId()));

                Integer bindingCount = this.couponsUsersMapper.selectCount(new QueryWrapper<CouponsUsers>().eq("activity_id", activity.getId()));

                //              验证库存是否足够发放给用户,已经绑定的+将要绑定的 > 活动总数量
                int userCouponCount = list.size() * activityCoupons.getLimitNum();

                int sum = userCouponCount + bindingCount;

                if (sum > activityCoupons.getTotalNum()) {
                    throw new BaseException(BusinessMessage.ACTIVITY_COUPON_NOT_ENOUGH_ERROR);
                }

                CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(activityCoupons.getBatchId());
//            绑定到定向活动绑定人员表
                for (UserVo userVo : list) {

//                验证用户是否已经导入到明细表中,有了无需再次导入
                    ActivityUser activityUser1 = this.activityUserMapper.selectOne(new QueryWrapper<ActivityUser>().eq("phone", userVo.getPhoneNum()));
                    if (activityUser1 != null) {
                        continue;
                    }

                    ActivityUser activityUser = new ActivityUser();
                    activityUser.setActivityId(activity.getId());
                    activityUser.setPhone(userVo.getPhoneNum());
                    activityUser.setUserId(Long.valueOf(userVo.getUserId()));
                    activityUser.setStatus(1);

                    //如果是活动进行中直接发放给用户，插入定向发放表
                    if (activity.getStatus() == 2) {
                        for (int i = 0; i < activityCoupons.getLimitNum(); i++) {
                            CouponsUsers couponsUsers = new CouponsUsers();
                            //        1.生成优惠券码
                            String code = TimeUtils.getGuid();
                            couponsUsers.setCouponsCode(code);
                            couponsUsers.setBatchId(activityCoupons.getBatchId());
                            couponsUsers.setActivityId(activity.getId());
                            couponsUsers.setUserId(Long.parseLong(userVo.getUserId()));
                            couponsUsers.setPhone(userVo.getPhoneNum());
                            couponsUsers.setCreateTime(LocalDateTime.now());
                            couponsUsers.setCreateBy(123456789L);
                            couponsUsers.setState(0);
//                        设置优惠券的有效日期
                            if (couponsBatch.getTimeLimit() == 1) {
                                couponsUsers.setStartTime(couponsBatch.getStartTime());
                                couponsUsers.setEndTime(couponsBatch.getEndTime());
                            }
                            if (couponsBatch.getTimeLimit() == 0) {
                                couponsUsers.setStartTime(LocalDateTime.now());
                                couponsUsers.setEndTime(LocalDateTime.now().plusDays(10));
                            }
                            couponsUsersMapper.insert(couponsUsers);

                            //                插入优惠券发放日志表
                            CouponsUsersLog couponsUsersLog = new CouponsUsersLog();
                            couponsUsersLog.setCreateTime(LocalDateTime.now());
                            couponsUsersLog.setOperateType(0);
                            couponsUsersLog.setCouponsId(couponsUsers.getId());
                            couponsUsersLog.setCreateName("广电测试");
                            couponsUsersLog.setCreateBy(123456789L);
                            couponsUsersLog.setCouponsCode(couponsUsers.getCouponsCode());
                            couponsUsersLog.setCouponsState(0);
                            couponsUsersLog.setOperateDesc("定向发放优惠券");
                            this.couponsUsersLogMapper.insert(couponsUsersLog);

//                        修改发放明细表中用户的发放状态
                            activityUser.setStatus(3);
                            this.activityUserMapper.insert(activityUser);
                        }
                    }
                    this.activityUserMapper.insert(activityUser);
                }

                log.info("定向发放优惠券活动导入用户列表结束");
            } else {
                String fileName = "error";
                try {
                    ExcelUtils.export(fileName, bindingUserWithFailVos, BindingUserWithFailVo.class, response);
                    return Response.fail("导入的手机号，部分不存在");
                } catch (Exception e) {
                    log.error("用户异常报表导出失败，exception", e);
                }
            }
        } else {
            throw new BaseException(BusinessMessage.ACTIVITY_COUPON_GET_USERINFO_ERROR);
        }
        return Response.success();
    }

    /**
     * 查看发放明细列表
     *
     * @param pageIndex
     * @param pageSize
     * @param dto
     * @return com.baomidou.mybatisplus.extension.plugins.pagination.Page<conson.tech.manage.coupons.entity.vo.BindingDetailVo>
     */
    @Override
    public GrantDetailVo bindingDetail(Integer pageIndex, Integer pageSize, BindingDetailDto dto) {

        GrantDetailVo grantDetailVo = new GrantDetailVo();

        log.info("分页查看发放明细列表");
        Page<BindingDetailVo> page = new Page<>(pageIndex, pageSize);
        //        导入总量，待发放，发放失败，发放成功
        Integer waitingCount = this.activityUserMapper.selectCount(new QueryWrapper<ActivityUser>().eq("status", 1).eq("activity_id", dto.getId()));
        Integer failCount = this.activityUserMapper.selectCount(new QueryWrapper<ActivityUser>().eq("status", 2).eq("activity_id", dto.getId()));
        Integer successCount = this.activityUserMapper.selectCount(new QueryWrapper<ActivityUser>().eq("status", 3).eq("activity_id", dto.getId()));
        Integer allCount = this.activityUserMapper.selectCount(new QueryWrapper<ActivityUser>().eq("activity_id", dto.getId()));

        grantDetailVo.setBindingDetailVoPage(this.activityUserMapper.bindingDetailList(page, dto));
        grantDetailVo.setFailCount(failCount);
        grantDetailVo.setWaitingCount(waitingCount);
        grantDetailVo.setSuccessCount(successCount);
        grantDetailVo.setTotalCount(allCount);
        log.info("分页查看发放明细列表完成");
        return grantDetailVo;


    }

    /**
     * （定时发放通过定时器）修改活动状态
     *
     * @return void
     */
    @Override
    @Transactional
    public void updateActivity() {
        //            验证活动是否在存在
        List<Activity> activities = this.activityMapper.selectActivityList();

        for (Activity activity : activities) {
            if (activity == null) {
                throw new BaseException(BusinessMessage.ACTIVITY_NOT_EXISTS_ERROR);
            }
//            定向发放活动
            if (activity.getCollectType() == 0 && activity.getGrantType() == 2 && LocalDateTime.now().getMinute() == activity.getGrantTime().getMinute()) {
                activity.setStatus(2);
                activity.setUpdateTime(LocalDateTime.now());
                activity.setUpdateBy(123456789L);
                this.activityMapper.updateById(activity);

                //修改领券活动表，录入活动操作日志表
                OperationLogDto opera1 = new OperationLogDto();
                opera1.setCreateBy("广电测试");
                opera1.setDomainId(activity.getId());
                opera1.setOperateDesc("修改发券活动");
                this.editLog(opera1);

            } else if (activity.getCollectType() == 0 && activity.getGrantType() == 2 && LocalDateTime.now().isAfter(activity.getGrantTime())) {
                activity.setStatus(3);
                activity.setUpdateTime(LocalDateTime.now());
                activity.setUpdateBy(123456789L);
                this.activityMapper.updateById(activity);

                //修改领券活动表，录入活动操作日志表
                OperationLogDto opera1 = new OperationLogDto();
                opera1.setCreateBy("广电测试");
                opera1.setDomainId(activity.getId());
                opera1.setOperateDesc("修改发券活动");
                this.editLog(opera1);
            }
//            直接领取的活动
            if (activity.getCollectType() == 1 && LocalDate.now().isAfter(activity.getEndTime())) {
                activity.setStatus(3);
                activity.setUpdateTime(LocalDateTime.now());
                this.activityMapper.updateById(activity);

                //修改领券活动表，录入活动操作日志表
                OperationLogDto opera1 = new OperationLogDto();
                opera1.setCreateBy("广电测试");
                opera1.setDomainId(activity.getId());
                opera1.setOperateDesc("修改非定向发放活动");
                this.editLog(opera1);

                List<ActivityCoupons> activityCoupons = this.activityCouponsMapper.selectList(new QueryWrapper<ActivityCoupons>().eq("activity_id", activity.getId()));

                for (ActivityCoupons activityCoupon : activityCoupons) {
                    //           从Redis中取出活动库存
                    String activityStock = (String) redisTemplate.opsForValue().get(CouponsConstants.ACTIVITY_COUPON_PREFIX + activity.getId() + ":" + activityCoupon.getBatchId());
                    if (activityStock != null) {
                        activityCoupon.setSurplusNum(Integer.valueOf(activityStock));
                    }
                    //                将直接领取的活动中的库存删除，同时将剩余库存插入到优惠券绑定表中
                    redisTemplate.delete(CouponsConstants.ACTIVITY_COUPON_PREFIX + activity.getId() + ":" + activityCoupon.getBatchId());
                    activityCoupon.setUpdateTime(LocalDateTime.now());
                    activityCoupon.setUpdateBy(123456789L);

                    this.activityCouponsMapper.updateById(activityCoupon);
                }

            }
        }
    }

    /**
     * 定时发放优惠券给用户
     *
     * @return void
     */
    @Override
    @Transactional
    public void grantCoupons() {
        //            验证活动是否在存在
        List<Activity> activities = this.activityMapper.selectActivityList();
        for (Activity activity : activities) {
            if (activity == null) {
                throw new BaseException(BusinessMessage.ACTIVITY_NOT_EXISTS_ERROR);
            }
//            只有活动为运行时且活动类型为定向发放才能发放优惠券
            if (activity.getStatus() == 2 && activity.getCollectType() == 0) {
                ActivityCoupons activityCoupons = this.activityCouponsMapper.selectOne(new QueryWrapper<ActivityCoupons>().eq("activity_id", activity.getId()));
                if (activityCoupons == null) {
                    throw new BaseException(BusinessMessage.ACTIVITY_COUPONS_NOT_EXISTS_ERROR);
                }
                CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(activityCoupons.getBatchId());

                List<ActivityUser> activityUsers = this.activityUserMapper.selectList(new QueryWrapper<ActivityUser>().eq("activity_id", activity.getId()).eq("status", 1));
                if (activityUsers != null && activityUsers.size() > 0) {
                    for (ActivityUser activityUser : activityUsers) {
//                        只有待发放的用户需要绑定优惠券
                        if (activityUser.getStatus() == 1) {
                            for (int i = 0; i < activityCoupons.getLimitNum(); i++) {
                                CouponsUsers couponsUsers = new CouponsUsers();
                                //        1.生成优惠券码
                                String code = TimeUtils.getGuid();
                                couponsUsers.setCouponsCode(code);
                                couponsUsers.setBatchId(activityCoupons.getBatchId());
                                couponsUsers.setActivityId(activity.getId());
                                couponsUsers.setUserId(activityUser.getUserId());
                                couponsUsers.setPhone(activityUser.getPhone());
                                couponsUsers.setCreateTime(LocalDateTime.now());
                                couponsUsers.setCreateBy(123456789L);
                                couponsUsers.setState(0);
                                couponsUsers.setStartTime(couponsBatch.getStartTime());
                                couponsUsers.setEndTime(couponsBatch.getEndTime());
                                couponsUsersMapper.insert(couponsUsers);

                                //                插入优惠券发放日志表
                                CouponsUsersLog couponsUsersLog = new CouponsUsersLog();
                                couponsUsersLog.setCreateTime(LocalDateTime.now());
                                couponsUsersLog.setOperateType(0);
                                couponsUsersLog.setCouponsId(couponsUsers.getId());
                                couponsUsersLog.setCreateName("广电测试");
                                couponsUsersLog.setCreateBy(123456789L);
                                couponsUsersLog.setCouponsCode(couponsUsers.getCouponsCode());
                                couponsUsersLog.setCouponsState(0);
                                couponsUsersLog.setOperateDesc("定向发放优惠券");
                                this.couponsUsersLogMapper.insert(couponsUsersLog);

//                        修改发放明细表中用户的发放状态
                                activityUser.setStatus(3);
                                this.activityUserMapper.updateById(activityUser);
                            }
                        }
                    }
                }
            }
        }
    }


    /**
     * 财务结算报表列表
     *
     * @param pageIndex
     * @param pageSize
     * @param dto
     * @return com.baomidou.mybatisplus.extension.plugins.pagination.Page<conson.tech.manage.coupons.entity.vo.FinanceDataPageVo>
     */
    @Override
    public Page<FinanceDataPageVo> financeDataList(Integer pageIndex, Integer pageSize, FinanceDataPageDto dto) {

        log.info("财务结算报表列表开始");
        Page<FinanceDataPageVo> page = new Page<>(pageIndex, pageSize);

        log.info("财务结算报表列表结束");
        return this.activityUserMapper.financeDataList(page, dto);
    }

    /**
     * 定时修改发放的优惠券中的优惠券的状态
     *
     * @return void
     */
    @Override
    public void updateCouponState() {
//         查找出所有的有效的优惠券
        List<CouponsUsers> validCoupons = this.couponsUsersMapper.selectList(new QueryWrapper<CouponsUsers>().eq("state", 0));
        for (CouponsUsers validCoupon : validCoupons) {
//            得到每张券的有效期
            CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(validCoupon.getBatchId());
//            如果当前时间已经在有效期后了，置为已过期
            if (LocalDateTime.now().isAfter(couponsBatch.getEndTime())) {
                validCoupon.setState(2);

                //                插入优惠券发放日志表
                CouponsUsersLog couponsUsersLog = new CouponsUsersLog();
                couponsUsersLog.setCreateTime(LocalDateTime.now());
                couponsUsersLog.setCouponsId(validCoupon.getId());
                couponsUsersLog.setCouponsCode(validCoupon.getCouponsCode());
                couponsUsersLog.setOperateDesc("修改优惠券的状态");
                couponsUsersLog.setCreateName("广电测试");
                couponsUsersLog.setCreateBy(123456789L);
                couponsUsersLog.setCouponsState(2);
                couponsUsersLog.setOperateType(0);
                this.couponsUsersLogMapper.insert(couponsUsersLog);
            }
        }
    }

    /**
     * 新增领券活动
     *
     * @param currentUserId
     * @param currentUsername
     * @param dto
     * @return conson.tech.core.response.Response
     */
    @Override
    @Transactional
    public Response addCouponActivity(Long currentUserId, String currentUsername, ActivitySaveDto dto) {
        log.info("添加领券活动开始");
        //        参数校验
//        校验活动是否存在
        Activity activity1 = this.activityMapper.selectOne(new QueryWrapper<Activity>().eq("activity_name", dto.getActivityName()));
        if (activity1 != null) {
            throw new BaseException(BusinessMessage.ACTIVITY__EXISTS_ERROR);
        }
//        定时发放日期必须大于当前日期
        if (dto.getGrantTime() != null && dto.getGrantTime().compareTo(LocalDateTime.now()) < 0) {
            throw new BaseException(BusinessMessage.GRANTTIME_ERROR);
        }
//        活动必须含有优惠券
        if (dto.getCouponSaveDtoList() == null) {
            throw new BaseException(BusinessMessage.COUPONS_NULL_ERROR);
        }

        //        添加领券活动信息
        Activity activity = new Activity();
        activity.setApplyId(currentUserId);
        activity.setApplyName(currentUsername);
        activity.setCreateBy(currentUserId);
        activity.setActivityName(dto.getActivityName());
        activity.setCollectType(dto.getCollectType());
        activity.setCreateTime(LocalDateTime.now());
        //        添加领券活动绑定券批次信息
        ActivityCoupons activityCoupons = new ActivityCoupons();

        if (dto.getCollectType() == 0) {
            //定向发放
            activity.setGrantType(dto.getGrantType());
            if (dto.getGrantType() == 2) {
                //设置定向发放优惠券时间
                activity.setGrantTime(dto.getGrantTime());
                activity.setStatus(1);
            } else if (dto.getGrantType() == 1) {
                activity.setStatus(2);
            }
            activity.setGrantMethod(1);
            activity.setArriveType(dto.getArriveType());
            activity.setMessageType(dto.getMessageType());
            if (dto.getMessageType() == 1) {
                activity.setPushContent(dto.getPushContent());
            }
            activity.setPushType(dto.getPushType());


            //插入领券活动表
            this.activityMapper.insert(activity);

            //插入领券活动表，录入活动操作日志表
            OperationLogDto opera = new OperationLogDto();
            opera.setCreateBy(currentUsername);
            opera.setDomainId(activity.getId());
            opera.setOperateDesc("创建领券活动");
            this.editLog(opera);


            for (ActivityCouponSaveDto activityCouponSaveDto : dto.getCouponSaveDtoList()) {
                CouponsBatch couponsBatch = this.couponsBatchMapper.selectOne(new QueryWrapper<CouponsBatch>().eq("id", activityCouponSaveDto.getBatchId()));
                if (couponsBatch == null) {
                    throw new BaseException(BusinessMessage.COUPONS_NOT_EXISTS_ERROR);
                }
//                校验券批次的数量是否大于0
                if (couponsBatch.getStockNum() <= 0) {
                    throw new BaseException(BusinessMessage.COUPON_BATCH_NOT_ENOUGH_ERROR);
                }
                //立即发放日期必须在优惠券的有效期范围内
//                判断批次有效期限制类型如果为绝对,必须在范围内
                if (couponsBatch.getTimeLimit() == 0 && LocalDateTime.now().isAfter(couponsBatch.getEndTime())) {
                    throw new BaseException(BusinessMessage.TRANSMISSION_TIME_ERROR);
                }
                //        单用户发放数量必须小于优惠券每人最大可领取数量且必须大于0，默认为1
                if ((couponsBatch.getLimitNum() != null && activityCouponSaveDto.getLimitNum() > couponsBatch.getLimitNum()) || activityCouponSaveDto.getLimitNum() <= 0) {
                    throw new BaseException(BusinessMessage.COUPON_NUM_ERROR);
                }
                activityCoupons.setActivityId(activity.getId());
                activityCoupons.setCreateBy(currentUserId);
                activityCoupons.setCreateTime(LocalDateTime.now());
                activityCoupons.setApplyId(currentUserId);
                activityCoupons.setBatchId(couponsBatch.getId());
                activityCoupons.setLimitNum(activityCouponSaveDto.getLimitNum());
                activityCoupons.setTotalNum(couponsBatch.getStockNum());

                this.activityCouponsMapper.insert(activityCoupons);

                //                    同时更新优惠券剩余数量
                CouponsBatch couponsBatch1 = new CouponsBatch();
                couponsBatch1.setId(couponsBatch.getId());
                couponsBatch1.setStockNum(couponsBatch.getStockNum() - activityCoupons.getTotalNum());
                this.couponsBatchMapper.updateById(couponsBatch1);

                //优惠券修改完成之后，录入优惠券操作日志表
                OperationLogDto opera1 = new OperationLogDto();
                opera1.setCreateBy(currentUsername);
                opera1.setDomainId(couponsBatch.getId());
                opera1.setOperateDesc("修改优惠券");
                this.editLog(opera1);
            }
        } else if (dto.getCollectType() == 1) {
//            LocalDateTime.parse(dto.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
            //        直接领取
            if (dto.getStartTime() != null && dto.getEndTime() != null) {
                activity.setStartTime(dto.getStartTime());
                activity.setEndTime(dto.getEndTime());
            }
            if (dto.getAvtivityRule() != null) {
                activity.setAvtivityRule(dto.getAvtivityRule());
            }
//            设置活动状态
            if (LocalDate.now().isBefore(dto.getStartTime())) {
//                初始状态
                activity.setStatus(1);
            }
//            开始日期=<当前日期<=结束日期
            boolean result = (LocalDate.now().isEqual(dto.getStartTime()) || LocalDate.now().isAfter(dto.getStartTime())) && (LocalDate.now().isBefore(dto.getEndTime()) || LocalDate.now().isEqual(dto.getEndTime()));
            if (result) {
                //  进行中状态
                activity.setStatus(2);
            }
            //插入领券活动表
            this.activityMapper.insert(activity);

            //插入领券活动表，录入活动操作日志表
            OperationLogDto opera2 = new OperationLogDto();
            opera2.setCreateBy(currentUsername);
            opera2.setDomainId(activity.getId());
            opera2.setOperateDesc("创建领券活动");
            this.editLog(opera2);

            for (ActivityCouponSaveDto activityCouponSaveDto : dto.getCouponSaveDtoList()) {
                boolean res = !((dto.getStartTime().isBefore(activityCouponSaveDto.getCouponStartTime()) || dto.getStartTime().isEqual(activityCouponSaveDto.getCouponStartTime())) && (dto.getEndTime().isAfter(activityCouponSaveDto.getCouponEndTime()) || dto.getEndTime().isEqual(activityCouponSaveDto.getCouponEndTime())));
                //       校验批次券的有效期在活动的有效期间
                if (dto.getStartTime() != null && dto.getEndTime() != null && activityCouponSaveDto.getCouponStartTime() != null && activityCouponSaveDto.getCouponEndTime() != null && res) {
                    throw new BaseException(BusinessMessage.COUPON_TIME_OUT_ERROR);
                }
                CouponsBatch couponsBatch = this.couponsBatchMapper.selectOne(new QueryWrapper<CouponsBatch>().eq("id", activityCouponSaveDto.getBatchId()));
                //                    校验优惠券批次信息是否存在
                if (couponsBatch == null) {
                    throw new BaseException(BusinessMessage.COUPONS_NOT_EXISTS_ERROR);
                }
                //                校验券批次的数量是否大于0
                if (couponsBatch.getStockNum() <= 0) {
                    throw new BaseException(BusinessMessage.COUPON_BATCH_NOT_ENOUGH_ERROR);
                }
                //                    判断批次有效期限制类型如果为绝对,直接领取活动必须在批次有效截止日期之前创建
                if (couponsBatch.getTimeLimit() == 0 && dto.getStartTime().isAfter(couponsBatch.getEndTime().toLocalDate())) {
                    throw new BaseException(BusinessMessage.TRANSMISSION_TIME_ERROR);
                }
                //        单用户发放数量必须小于优惠券每人最大可领取数量
                if ((couponsBatch.getLimitNum() != null && activityCouponSaveDto.getLimitNum() > couponsBatch.getLimitNum()) || activityCouponSaveDto.getLimitNum() <= 0) {
                    throw new BaseException(BusinessMessage.COUPON_NUM_ERROR);
                }
                //                校验活动总数量不能超过优惠券剩余数量
                if (activityCouponSaveDto.getTotalNum() > couponsBatch.getStockNum()) {
                    throw new BaseException(BusinessMessage.Activity_NUM_ERROR);
                }
                activityCoupons.setActivityId(activity.getId());
                activityCoupons.setBatchId(couponsBatch.getId());

                activityCoupons.setStartTime(activityCouponSaveDto.getCouponStartTime());
                activityCoupons.setEndTime(activityCouponSaveDto.getCouponEndTime());
                activityCoupons.setLimitNum(activityCouponSaveDto.getLimitNum());
                activityCoupons.setTotalNum(activityCouponSaveDto.getTotalNum());

                activityCoupons.setCreateBy(currentUserId);
                activityCoupons.setCreateTime(LocalDateTime.now());
                activityCoupons.setApplyId(currentUserId);
                this.activityCouponsMapper.insert(activityCoupons);

                //将参与活动的批次信息中库存存入到redis中
                redisTemplate.opsForValue().set(CouponsConstants.ACTIVITY_COUPON_PREFIX + activity.getId() + ":" + couponsBatch.getId(), activityCouponSaveDto.getTotalNum().toString());
                //    同时更新优惠券剩余数量
                couponsBatch.setId(couponsBatch.getId());
                couponsBatch.setStockNum(couponsBatch.getStockNum() - activityCouponSaveDto.getTotalNum());
                this.couponsBatchMapper.updateById(couponsBatch);

                //优惠券修改完成之后，录入优惠券操作日志表
                OperationLogDto opera3 = new OperationLogDto();
                opera3.setCreateBy(currentUsername);
                opera3.setDomainId(couponsBatch.getId());
                opera3.setOperateDesc("修改优惠券");
                this.editLog(opera3);
            }
        }
        log.info("添加领券活动结束");
        return Response.success(activity.getId());
    }

    /**
     * 修改领券活动
     *
     * @param currentUserId
     * @param currentUsername
     * @param activityId
     * @param dto
     * @return conson.tech.core.response.Response
     */
    @Override
    public Response editCouponActivity(Long currentUserId, String currentUsername, Long activityId, ActivityEditDto dto) {

        log.info("修改领券活动开始");
        //        参数校验
        Activity activity = this.activityMapper.selectById(activityId);
        if (activity == null) {
            throw new BaseException(BusinessMessage.ACTIVITY_NOT_EXISTS_ERROR);
        }
        //        校验活动名称是否存在
        Activity activity1 = this.activityMapper.selectOne(new QueryWrapper<Activity>().ne("id", activityId).eq("activity_name", dto.getActivityName()));
        if (activity1 != null) {
            throw new BaseException(BusinessMessage.ACTIVITY__EXISTS_ERROR);
        }

        activity.setUpdateBy(currentUserId);
        activity.setUpdateTime(LocalDateTime.now());
        activity.setActivityName(dto.getActivityName());
        activity.setCollectType(dto.getCollectType());

        List<ActivityCoupons> activityCouponsList = this.activityCouponsMapper.selectList(new QueryWrapper<ActivityCoupons>().eq("activity_id", activity.getId()));

//        初始化的定向活动（定时发放）修改
        //            定向发放 只能修改定时发放，可以将定时发放修改为立即发放
        if (dto.getCollectType() == 0) {
            activity.setMessageType(dto.getMessageType());
            if (dto.getMessageType() == 1) {
                activity.setPushContent(dto.getPushContent());
            }
            activity.setPushType(dto.getPushType());
            activity.setArriveType(dto.getArriveType());
            activity.setGrantType(dto.getGrantType());
            if (dto.getGrantType() == 1) {
                activity.setGrantTime(null);
                activity.setStatus(2);
            }
            if (dto.getGrantType() == 2) {
                //        定时发放日期必须大于当前日期
                if (dto.getGrantTime() != null && dto.getGrantTime().isBefore(LocalDateTime.now())) {
                    throw new BaseException(BusinessMessage.GRANTTIME_ERROR);
                }
                activity.setGrantTime(dto.getGrantTime());
                activity.setStatus(2);
            }
            this.activityMapper.updateById(activity);

            //修改领券活动表，录入活动操作日志表
            OperationLogDto opera = new OperationLogDto();
            opera.setCreateBy(currentUsername);
            opera.setDomainId(activity.getId());
            opera.setOperateDesc("修改发券活动");
            this.editLog(opera);

            //            修改优惠券绑定信息
            for (ActivityCoupons activityCoupons : activityCouponsList) {

                for (ActivityCouponSaveDto activityCouponSaveDto : dto.getCouponSaveDtoList()) {
                    CouponsBatch couponsBatch = this.couponsBatchMapper.selectOne(new QueryWrapper<CouponsBatch>().eq("id", activityCoupons.getBatchId()));
                    //        单用户发放数量必须小于优惠券每人最大可领取数量且必须大于0，默认为1
                    if ((couponsBatch.getLimitNum() != null && activityCouponSaveDto.getLimitNum() > couponsBatch.getLimitNum()) || activityCouponSaveDto.getLimitNum() <= 0) {
                        throw new BaseException(BusinessMessage.COUPON_NUM_ERROR);
                    }
                    activityCoupons.setLimitNum(activityCouponSaveDto.getLimitNum());
                    activityCoupons.setUpdateBy(currentUserId);
                    activityCoupons.setUpdateTime(LocalDateTime.now());
                    this.activityCouponsMapper.updateById(activityCoupons);
                }
            }
        }
//        未开始的直接领取活动修改
        if (activity.getCollectType() == 1) {
//            直接发放
            activity.setStartTime(dto.getStartTime());
            activity.setEndTime(dto.getEndTime());
            if (dto.getAvtivityRule() != null) {
                activity.setAvtivityRule(dto.getAvtivityRule());
            }
//            设置活动状态
            if (LocalDate.now().isBefore(dto.getStartTime())) {
//                初始状态
                activity.setStatus(1);
            }
            //            开始日期=<当前日期<=结束日期
            boolean result = (LocalDate.now().isEqual(dto.getStartTime()) || LocalDate.now().isAfter(dto.getStartTime())) && (LocalDate.now().isBefore(dto.getEndTime()) || LocalDate.now().isEqual(dto.getEndTime()));
            if (result) {
                //  进行中状态
                activity.setStatus(2);
            }
            this.activityMapper.updateById(activity);

            //修改领券活动表，录入活动操作日志表
            OperationLogDto opera1 = new OperationLogDto();
            opera1.setCreateBy(currentUsername);
            opera1.setDomainId(activity.getId());
            opera1.setOperateDesc("修改发券活动");
            this.editLog(opera1);

//            修改优惠券批次信息
            for (ActivityCouponSaveDto activityCouponSaveDto : dto.getCouponSaveDtoList()) {
                boolean res = !((dto.getStartTime().isBefore(activityCouponSaveDto.getCouponStartTime()) || dto.getStartTime().isEqual(activityCouponSaveDto.getCouponStartTime())) && (dto.getEndTime().isAfter(activityCouponSaveDto.getCouponEndTime()) || dto.getEndTime().isEqual(activityCouponSaveDto.getCouponEndTime())));
                //       校验批次券的有效期在活动的有效期间
                if (dto.getStartTime() != null && dto.getEndTime() != null && activityCouponSaveDto.getCouponStartTime() != null && activityCouponSaveDto.getCouponEndTime() != null && res) {
                    throw new BaseException(BusinessMessage.COUPON_TIME_OUT_ERROR);
                }
                ActivityCoupons activityCoupons = this.activityCouponsMapper.selectOne(new QueryWrapper<ActivityCoupons>().eq("activity_id", activityId).eq("batch_id", activityCouponSaveDto.getBatchId()));
                CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(activityCoupons.getBatchId());
                //                    判断批次有效期限制类型如果为绝对,直接领取活动必须在批次有效截止日期之前创建
                if (couponsBatch.getTimeLimit() == 0 && dto.getStartTime().isAfter(couponsBatch.getEndTime().toLocalDate())) {
                    throw new BaseException(BusinessMessage.TRANSMISSION_TIME_ERROR);
                }
                //        单用户发放数量必须小于优惠券每人最大可领取数量且必须大于0，默认为1
                if ((couponsBatch.getLimitNum() != null && activityCouponSaveDto.getLimitNum() > couponsBatch.getLimitNum()) || activityCouponSaveDto.getLimitNum() <= 0) {
                    throw new BaseException(BusinessMessage.COUPON_NUM_ERROR);
                }
                //                校验活动总数量不能超过优惠券剩余数量（这里的剩余数量需要重新查询优惠券批次的剩余数量）
                if (activityCouponSaveDto.getTotalNum() > couponsBatch.getStockNum()) {
                    throw new BaseException(BusinessMessage.Activity_NUM_ERROR);
                }
                RLock lock = redissonClient.getLock(CouponsConstants.ACTIVITY_DIRECT_UPDATE_STOCK_LOCK);

                lock.lock(10, TimeUnit.SECONDS);

                try {
                    //                校验 活动总数量必须大于活动剩余库存
                    String surplusNum = redisTemplate.opsForValue().get(CouponsConstants.ACTIVITY_COUPON_PREFIX + activity.getId() + ":" + activityCoupons.getBatchId());
                    if (surplusNum != null) {
//                        已经消耗了数量
                        Integer remainNum = activityCoupons.getTotalNum() - Integer.parseInt(surplusNum);
                        if (activityCouponSaveDto.getTotalNum() < remainNum) {
                            throw new BaseException(BusinessMessage.ACTIVITY_SUM_NUM_LESS_THAN_REMAIN_ERROR);
                        }
                    }
                    //将参与活动的批次信息中库存存入到redis中
                    redisTemplate.opsForValue().set(CouponsConstants.ACTIVITY_COUPON_PREFIX + activity.getId() + ":" + activityCoupons.getBatchId(), activityCouponSaveDto.getTotalNum().toString());
                } finally {
                    lock.unlock();
                }

                activityCoupons.setStartTime(activityCouponSaveDto.getCouponStartTime());
                activityCoupons.setEndTime(activityCouponSaveDto.getCouponEndTime());
                activityCoupons.setLimitNum(activityCouponSaveDto.getLimitNum());


                //    同时更新优惠券剩余数量 进一步扣减  100   50
                //    同时更新优惠券剩余数量  进一步添加 100   200
                if (activityCouponSaveDto.getTotalNum() >= activityCoupons.getTotalNum()) {
                    couponsBatch.setStockNum(couponsBatch.getStockNum() - (activityCouponSaveDto.getTotalNum() - activityCoupons.getTotalNum()));
                } else {
                    couponsBatch.setStockNum(couponsBatch.getStockNum() + (activityCoupons.getTotalNum() - activityCouponSaveDto.getTotalNum()));
                }
//                修改完成优惠券数据
                this.couponsBatchMapper.updateById(couponsBatch);

//                修改领券活动绑定的总数

                activityCoupons.setTotalNum(activityCouponSaveDto.getTotalNum());
                activityCoupons.setUpdateBy(currentUserId);
                activityCoupons.setUpdateTime(LocalDateTime.now());
                this.activityCouponsMapper.updateById(activityCoupons);


                //优惠券修改完成之后，录入优惠券操作日志表
                OperationLogDto opera2 = new OperationLogDto();
                opera2.setCreateBy(currentUsername);
                opera2.setDomainId(couponsBatch.getId());
                opera2.setOperateDesc("修改优惠券");
                this.editLog(opera2);
            }
        }
        log.info("修改领券活动结束");
        return Response.success(activity.getId());
    }

    /**
     * 领券活动日志列表
     *
     * @param pageIndex
     * @param pageSize
     * @param id
     * @param type
     * @return com.baomidou.mybatisplus.extension.plugins.pagination.Page<conson.tech.manage.coupons.entity.pojo.OperationLog>
     */
    @Override
    public Page<OperationLogVo> couponActivityLogList(Integer pageIndex, Integer pageSize, Long id, Integer type) {
        log.info("分页查询领券活动日志列表开始");
        Page<OperationLogVo> page = new Page<>(pageIndex, pageSize);
        log.info("分页查询领券活动日志列表结束");
        return this.operationLogMapper.couponActivityLogList(page, id, type);
    }

    /**
     * 财务结算报表结算
     *
     * @param currentUserId
     * @param currentUsername
     * @param id
     * @return conson.tech.core.response.Response
     */
    @Override
    public Response settleFinanceData(Long currentUserId, String currentUsername, Long id) {

        log.info("财务结算报表结算开始");

        SettlementReport settlementReport = this.settlementReportMapper.selectById(id);
        if (settlementReport == null) {
            throw new BaseException(BusinessMessage.SETTLEMENT_REPORT_DATA_ERROR);
        }
        if (settlementReport.getStatus() == 1) {
            throw new BaseException(BusinessMessage.SETTLEMENT_REPORT_DATA_CLOSED_ERROR);
        }
        settlementReport.setStatus(1);
        settlementReport.setUpdateBy(currentUsername);
        settlementReport.setUpdateTime(LocalDateTime.now());

        this.settlementReportMapper.updateById(settlementReport);


        //优惠券修改完成之后，录入优惠券操作日志表
        OperationLogDto opera2 = new OperationLogDto();
        opera2.setCreateBy(currentUsername);
        opera2.setDomainId(settlementReport.getId());
        opera2.setOperateDesc("结算财务");
        this.editFinanceLog(opera2);

        log.info("财务结算报表结算结束");
        return Response.success(settlementReport.getId());
    }


    /**
     * 领券活动列表
     *
     * @param pageIndex
     * @param pageSize
     * @param dto
     * @return com.baomidou.mybatisplus.extension.plugins.pagination.Page<conson.tech.manage.coupons.entity.vo.ActivityPageVo>
     */
    @Override
    public Page<ActivityPageVo> couponActivityList(Integer pageIndex, Integer pageSize, ActivityPageDto dto) {

        log.info("分页查询领券活动列表");
        Page<ActivityPageVo> page = new Page<>(pageIndex, pageSize);
        log.info("分页查询领券活动列表完成");
        dto.setActivityName(dto.getApplyName().trim());
        return this.activityMapper.couponActivityList(page, dto);
    }

    /**
     * 查看领券活动
     *
     * @param id
     * @return conson.tech.core.response.Response
     */
    @Override
    public Response getCouponActivity(Long id) {

        log.info("查看领券活动详情");

        Activity activity = this.activityMapper.selectById(id);
        if (activity == null) {
            throw new BaseException(BusinessMessage.ACTIVITY_NOT_EXISTS_ERROR);
        }
        ActivityDetailVo activityDetailVo = new ActivityDetailVo();
        activityDetailVo.setActivityName(activity.getActivityName());
        activityDetailVo.setId(activity.getId());
        activityDetailVo.setCollectType(activity.getCollectType());
        activityDetailVo.setStatus(activity.getStatus());
        if (activity.getStartTime() != null) {
            activityDetailVo.setStartTime(activity.getStartTime());
        }
        if (activity.getEndTime() != null) {
            activityDetailVo.setEndTime(activity.getEndTime());
        }
        if (activity.getAvtivityRule() != null) {
            activityDetailVo.setAvtivityRule(activity.getAvtivityRule());
        }

//        查询活动绑定的优惠券信息
        List<ActivityCouponDetailVo> activityCouponsList = this.activityCouponsMapper.selectAll(activity.getId());
        if (activity.getCollectType() == 0) {
//             定向发放
            activityDetailVo.setGrantMethod(activity.getGrantMethod());
            activityDetailVo.setGrantType(activity.getGrantType());
            activityDetailVo.setPushType(activity.getPushType());
            activityDetailVo.setPushContent(activity.getPushContent());
            activityDetailVo.setMessageType(activity.getMessageType());
            activityDetailVo.setArriveType(activity.getArriveType());
            if (activity.getGrantTime() != null) {
                activityDetailVo.setGrantTime(activity.getGrantTime());
            }
            if (activityCouponsList != null && activityCouponsList.size() > 0) {
                List<ActivityCouponDetailVo> collect = activityCouponsList.stream().map(coupon -> {

                    ActivityCouponDetailVo activityCouponDetailVo = new ActivityCouponDetailVo();
                    activityCouponDetailVo.setBatchId(coupon.getBatchId());
                    activityCouponDetailVo.setBatchName(coupon.getBatchName());
                    activityCouponDetailVo.setLimitNum(coupon.getLimitNum());
                    activityCouponDetailVo.setTotalNum(coupon.getTotalNum());
                    return coupon;
                }).collect(Collectors.toList());
                activityDetailVo.setCouponDetailVos(collect);
            }

        } else if (activity.getCollectType() == 1) {
//             直接领取
            List<ActivityCouponDetailVo> collect = activityCouponsList.stream().map(coupon -> {
                ActivityCouponDetailVo activityCouponDetailVo = new ActivityCouponDetailVo();
                activityCouponDetailVo.setBatchId(coupon.getBatchId());
                activityCouponDetailVo.setBatchName(coupon.getBatchName());
                activityCouponDetailVo.setLimitNum(coupon.getLimitNum());
                activityCouponDetailVo.setStartTime(coupon.getStartTime());
                activityCouponDetailVo.setEndTime(coupon.getEndTime());
                //           从Redis中取出活动库存
                String activityStock = redisTemplate.opsForValue().get(CouponsConstants.ACTIVITY_COUPON_PREFIX + activity.getId() + ":" + coupon.getBatchId());
                if (activityStock != null) {
                    activityCouponDetailVo.setSurplusNum(Integer.valueOf(activityStock));
                }
                activityCouponDetailVo.setTotalNum(coupon.getTotalNum());
                return activityCouponDetailVo;
            }).collect(Collectors.toList());
            activityDetailVo.setCouponDetailVos(collect);
        }
        log.info("查看领券活动详情完成");
        return Response.success(activityDetailVo);
    }


    /**
     * 通用日志写入方法
     * zyf
     * 2020/07/22
     *
     * @param dto 日志入参
     */
    private Response editLog(OperationLogDto dto) {
        try {
            log.info("开始写入日志操作表");
            OperationLog operationLog = new OperationLog();
            operationLog.setType(1);
            operationLog.setCreateBy(dto.getCreateBy());
            operationLog.setCreateTime(LocalDateTime.now());
            operationLog.setDomainId(dto.getDomainId());
            operationLog.setOperateDesc(dto.getOperateDesc());
            operationLog.setOperateType(0);
            operationLog.setRemark(dto.getRemark());
            this.operationLogMapper.insert(operationLog);
            log.info("日志操作表填写完成");
            return Response.success();
        } catch (Exception e) {
            log.error("写入日志操作表失败", e);
            throw new BaseException(BusinessMessage.OPERATION_LOG_WRITE_ERROR);
        }
    }

    private Response editFinanceLog(OperationLogDto dto) {
        try {
            log.info("开始写入日志操作表");
            OperationLog operationLog = new OperationLog();
            operationLog.setType(2);
            operationLog.setCreateBy(dto.getCreateBy());
            operationLog.setCreateTime(LocalDateTime.now());
            operationLog.setDomainId(dto.getDomainId());
            operationLog.setOperateDesc(dto.getOperateDesc());
            operationLog.setOperateType(0);
            operationLog.setRemark(dto.getRemark());
            this.operationLogMapper.insert(operationLog);
            log.info("日志操作表填写完成");
            return Response.success();
        } catch (Exception e) {
            log.error("写入日志操作表失败", e);
            throw new BaseException(BusinessMessage.OPERATION_LOG_WRITE_ERROR);
        }
    }


    /**
     * 根据搜索条件查询优惠券列表
     * zyf
     * 2020/7/23
     *
     * @param pageIndex
     * @param pageSize
     * @param dto
     */
    @Override
    public Page<CouponsBatchCenterVo> queryCouponsList(Integer pageSize, Integer pageIndex, CouponsCenterActivityDto dto) {

        try {
            log.info("开始查询优惠券批次列表");

            //构建分页查询条件
            Page<CouponsBatchCenterVo> page = new Page<>(pageIndex, pageSize);

            page = this.couponsBatchMapper.queryCouponsActivityList(page, dto);

            log.info("结束查询优惠券批次列表");
            return page;
        } catch (Exception e) {
            log.error("查询优惠券批次信息失败", e);
            throw new BaseException(BusinessMessage.COUPONS_LIST_ERROR);
        }
    }

    /**
     * 当前批次优惠券剩余数量
     *
     * @param activityId
     * @return java.lang.Integer
     */
    @Override
    public Integer activityCouponRemain(Long activityId) {
        ActivityCoupons activityCoupons = this.activityCouponsMapper.selectOne(new QueryWrapper<ActivityCoupons>().eq("activity_id", activityId));
        Integer totalNum = activityCoupons.getTotalNum();

        Integer integer = this.activityUserMapper.selectCount(new QueryWrapper<ActivityUser>().eq("activity_id", activityId).eq("status", 3));
        return totalNum - integer;
    }

    /**
     * 优惠券消息中心列表
     *
     * @param pageIndex
     * @param pageSize
     * @param dto
     * @return com.baomidou.mybatisplus.extension.plugins.pagination.Page<conson.tech.manage.coupons.entity.vo.CouponMessagePageVo>
     */
    @Override
    public Page<CouponMessagePageVo> couponMessageList1(Integer pageIndex, Integer pageSize, CouponMessagePageDto dto) {
        log.info("优惠券消息中心列表开始");
        Page<CouponMessagePageVo> page = new Page<>(pageIndex, pageSize);

        log.info("优惠券消息中心列表结束");
        return this.activityUserMapper.couponMessageList1(page, dto);
    }

    /**
     * TODO 月初统计上个月的财务报表
     *
     * @return void
     */
    @Override
    public void settlement() {

        //        统计上个月的已使用优惠券发放信息
        List<CouponsUsers> couponsUsers = this.couponsUsersMapper.selectList(
                new QueryWrapper<CouponsUsers>()
                        .select("*,COUNT(batch_id) AS batchNum")
                        //                核销时间在上个月
                        .between("apply_time", TimeUtils.getlastMonthFirstDay(), TimeUtils.getlastMonthLastDay())
                        .eq("state", 1)
                        .groupBy("using_id", "batch_id"));
        //统计各商户的财务数据
        if (couponsUsers != null && couponsUsers.size() > 0) {

            for (CouponsUsers couponsUser : couponsUsers) {

//                   统计商户财务的数据
//                   统计上个月的财务统计信息
                SettlementReport settlementReport = new SettlementReport();
                settlementReport.setStatus(0);
                settlementReport.setCreateBy("广电测试");
                settlementReport.setCreateTime(LocalDateTime.now());
                settlementReport.setApplyId(123456789L);
//                   获取上个月的日期
                settlementReport.setYMonth(TimeUtils.getLastMonth());
                //            获取优惠券批次信息
                CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(couponsUser.getBatchId());
                //            获取优惠券批次信息
                settlementReport.setBatchId(couponsBatch.getId());
                settlementReport.setBatchName(couponsBatch.getBatchName());
                settlementReport.setProvider(couponsBatch.getProvider());

                //                        TODO 根据费用归属来判断
                //            获取优惠券批次费用归属信息 （费用占比）
                CouponsCostProvider couponsCostProvider = this.couponsCostProviderMapper.selectOne(new QueryWrapper<CouponsCostProvider>().eq("batch_id", couponsBatch.getId()));
//                        如果type = 0 便捷青岛
//                          如果是type = 1  需要根据usingId来判断
                settlementReport.setProviderCode(couponsCostProvider.getType());
                settlementReport.setCostRatio(couponsCostProvider.getCostRatio());

                //                        获取优惠券批次商户信息
                CouponsUsingRange usingRange = this.couponsUsingRangeMapper.selectOne(new QueryWrapper<CouponsUsingRange>().eq("batch_id", couponsBatch.getId()).eq("using_id", couponsUser.getUsingId()));
                settlementReport.setShopId(usingRange.getUsingId());
                MerchantInformation merchantInformation = this.merchantInformationMapper.selectOne(new QueryWrapper<MerchantInformation>().eq("merchant_id", usingRange.getUsingId()));
                settlementReport.setShopName(merchantInformation.getMerchantName());
                //        查询出批次的相关财务统计信息
                //            使用数量
                Integer usedNum = couponsUser.getBatchNum();
                //            核销金额
                BigDecimal applieNumMoney = couponsBatch.getBatchMoney().multiply(new BigDecimal(usedNum));

                settlementReport.setUseNum(usedNum);
                settlementReport.setWrittenMoney(applieNumMoney);

                this.settlementReportMapper.insert(settlementReport);

                //优惠券修改完成之后，录入财务报表操作日志表
                OperationLogDto opera2 = new OperationLogDto();
                opera2.setCreateBy("广电测试");
                opera2.setDomainId(settlementReport.getId());
                opera2.setOperateDesc("创建财务报表");
                this.editFinanceLog(opera2);
            }
        }


        List<CouponsUsers> couponsUsers1 = this.couponsUsersMapper.selectList(
                new QueryWrapper<CouponsUsers>()
                        .select("*,COUNT(batch_id) AS batchReturnNum")
//                        返还时间，上个月内
                        .between("refund_time", TimeUtils.getlastMonthFirstDay(), TimeUtils.getlastMonthLastDay())
                        //        核销时间小于上个月月初第一天
                        .le("apply_time", TimeUtils.getlastMonthFirstDay())
                        .eq("state", 0)
                        .groupBy("using_id", "batch_id"));
        //统计各商户的财务数据
        if (couponsUsers1 != null && couponsUsers1.size() > 0) {

            for (CouponsUsers couponsUser : couponsUsers1) {

                //            获取优惠券批次信息
                CouponsBatch couponsBatch = this.couponsBatchMapper.selectById(couponsUser.getBatchId());
                //                        获取优惠券批次商户信息
                CouponsUsingRange usingRange = this.couponsUsingRangeMapper.selectOne(new QueryWrapper<CouponsUsingRange>().eq("batch_id", couponsBatch.getId()).eq("using_id", couponsUser.getUsingId()));

                //        查询出批次的相关财务统计信息
                //            返还数量
                Integer refundNum = couponsUser.getBatchReturnNum();
                //            返还金额
                BigDecimal refundMone = couponsBatch.getBatchMoney().multiply(new BigDecimal(couponsUser.getRefundCount()));

//                查询上个月的退还财务统计报表，shop_id+batch_id+上个月，是否已经统计过，如果有直接更新，没有重新插入新的报表数据
                SettlementReport settlementReport1 = this.settlementReportMapper.selectOne(new QueryWrapper<SettlementReport>().eq("batch_id", couponsBatch.getId()).eq("shopId", couponsUser.getUsingId()).eq("y_month", TimeUtils.getLastMonth()));
                if (settlementReport1 == null) {
                    SettlementReport settlementReport = new SettlementReport();
//                    新增 获取基础财务数据进行重新插入
                    settlementReport.setStatus(0);
                    settlementReport.setCreateBy("广电测试");
                    settlementReport.setCreateTime(LocalDateTime.now());
                    settlementReport.setApplyId(123456789L);
//                   获取上个月的日期
                    settlementReport.setYMonth(TimeUtils.getLastMonth());

                    settlementReport.setBatchId(couponsBatch.getId());
                    settlementReport.setBatchName(couponsBatch.getBatchName());
                    settlementReport.setProvider(couponsBatch.getProvider());
                    CouponsCostProvider couponsCostProvider = this.couponsCostProviderMapper.selectOne(new QueryWrapper<CouponsCostProvider>().eq("batch_id", couponsBatch.getId()));
//                        如果type = 0 便捷青岛
//                          如果是type = 1  需要根据usingId来判断
                    settlementReport.setProviderCode(couponsCostProvider.getType());
                    settlementReport.setCostRatio(couponsCostProvider.getCostRatio());

                    settlementReport.setShopId(usingRange.getUsingId());

                    MerchantInformation merchantInformation = this.merchantInformationMapper.selectOne(new QueryWrapper<MerchantInformation>().eq("merchant_id", usingRange.getUsingId()));
                    settlementReport.setShopName(merchantInformation.getMerchantName());

                    settlementReport.setRefundNum(refundNum);
                    settlementReport.setRefundMoney(refundMone);

                    this.settlementReportMapper.insert(settlementReport);

                    //优惠券修改完成之后，录入财务报表操作日志表
                    OperationLogDto opera2 = new OperationLogDto();
                    opera2.setCreateBy("广电测试");
                    opera2.setDomainId(settlementReport.getId());
                    opera2.setOperateDesc("创建财务报表");
                    this.editFinanceLog(opera2);
                } else {
//                    更新原先的财务数据
                    settlementReport1.setRefundNum(refundNum);
                    settlementReport1.setRefundMoney(refundMone);
                    this.settlementReportMapper.updateById(settlementReport1);

                    //优惠券修改完成之后，录入财务报表操作日志表
                    OperationLogDto opera2 = new OperationLogDto();
                    opera2.setCreateBy("广电测试");
                    opera2.setDomainId(settlementReport1.getId());
                    opera2.setOperateDesc("修改财务报表");
                    this.editFinanceLog(opera2);
                }

            }
        }
    }
}
